001 /*
002 * Copyright 2004-2005 Stephen McConnell
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.util;
020
021 import java.io.File;
022 import java.io.FileNotFoundException;
023 import java.io.InputStream;
024 import java.util.ArrayList;
025 import java.util.Properties;
026
027 import javax.xml.parsers.DocumentBuilder;
028 import javax.xml.parsers.DocumentBuilderFactory;
029
030 import org.w3c.dom.Document;
031 import org.w3c.dom.Element;
032 import org.w3c.dom.Node;
033 import org.w3c.dom.NodeList;
034
035 /**
036 * Utility class supporting the translation of DOM content into local child, children,
037 * attribute and value values.
038 *
039 * @author <a href="http://www.dpml.net">The Digital Product Meta Library</a>
040 * @version 1.0.0
041 */
042 public final class ElementHelper
043 {
044 private ElementHelper()
045 {
046 // utility class
047 }
048
049 /**
050 * Return the root element of the supplied file.
051 * @param definition the file to load
052 * @return the root element
053 * @exception Exception if the error occurs during root element establishment
054 */
055 public static Element getRootElement( final File definition )
056 throws Exception
057 {
058 if( !definition.exists() )
059 {
060 throw new FileNotFoundException( definition.toString() );
061 }
062
063 if( !definition.isFile() )
064 {
065 final String error =
066 "Source is not a file: " + definition;
067 throw new IllegalArgumentException( error );
068 }
069
070 final DocumentBuilderFactory factory =
071 DocumentBuilderFactory.newInstance();
072 factory.setValidating( false );
073 factory.setNamespaceAware( false );
074 final Document document =
075 factory.newDocumentBuilder().parse( definition );
076 return document.getDocumentElement();
077 }
078
079 /**
080 * Return the root element of the supplied input stream.
081 * @param input the input stream containing a XML definition
082 * @return the root element
083 * @exception Exception if an error occurs
084 */
085 public static Element getRootElement( final InputStream input )
086 throws Exception
087 {
088 final DocumentBuilderFactory factory =
089 DocumentBuilderFactory.newInstance();
090 factory.setValidating( false );
091 factory.setNamespaceAware( false );
092 factory.setExpandEntityReferences( false );
093 DocumentBuilder builder = factory.newDocumentBuilder();
094 return getRootElement( builder, input );
095 }
096
097 /**
098 * Return the root element of the supplied input stream.
099 * @param builder the document builder
100 * @param input the input stream containing a XML definition
101 * @return the root element
102 * @exception Exception if an error occurs
103 */
104 public static Element getRootElement( final DocumentBuilder builder, final InputStream input )
105 throws Exception
106 {
107 final Document document = builder.parse( input );
108 return document.getDocumentElement();
109 }
110
111 /**
112 * Return a named child relative to a supplied element.
113 * @param root the parent DOM element
114 * @param name the name of a child element
115 * @return the child element of null if the child does not exist
116 */
117 public static Element getChild( final Element root, final String name )
118 {
119 if( null == root )
120 {
121 return null;
122 }
123 Element[] children = getChildren( root );
124 for( int i=0; i<children.length; i++ )
125 {
126 Element child = children[i];
127 if( name.equals( child.getTagName() ) )
128 {
129 return child;
130 }
131 }
132 return null;
133 }
134
135 /**
136 * Return all children matching the supplied element name.
137 * @param root the parent DOM element
138 * @param name the name against which child element will be matched
139 * @return the array of child elements with a matching name
140 */
141 public static Element[] getChildren( final Element root, final String name )
142 {
143 if( null == root )
144 {
145 return new Element[0];
146 }
147 Element[] children = getChildren( root );
148 final ArrayList result = new ArrayList();
149 for( int i=0; i<children.length; i++ )
150 {
151 final Element child = children[i];
152 if( name.equals( child.getTagName() ) )
153 {
154 result.add( child );
155 }
156 }
157 return (Element[]) result.toArray( new Element[0] );
158 }
159
160 /**
161 * Return all children of the supplied parent.
162 * @param root the parent DOM element
163 * @return the array of all children
164 */
165 public static Element[] getChildren( final Element root )
166 {
167 if( null == root )
168 {
169 return new Element[0];
170 }
171 final NodeList list = root.getChildNodes();
172 final int n = list.getLength();
173 if( n < 1 )
174 {
175 return new Element[0];
176 }
177 final ArrayList result = new ArrayList();
178 for( int i=0; i < n; i++ )
179 {
180 final Node item = list.item( i );
181 if( item instanceof Element )
182 {
183 result.add( item );
184 }
185 }
186 return (Element[]) result.toArray( new Element[0] );
187 }
188
189 /**
190 * Return the value of an element.
191 * @param node the DOM node
192 * @return the node value
193 */
194 public static String getValue( final Element node )
195 {
196 if( null == node )
197 {
198 return null;
199 }
200 String value;
201 if( node.getChildNodes().getLength() > 0 )
202 {
203 value = node.getFirstChild().getNodeValue();
204 }
205 else
206 {
207 value = node.getNodeValue();
208 }
209 //return normalize( value );
210 return value;
211 }
212
213 /**
214 * Return the value of an element attribute.
215 * @param node the DOM node
216 * @param key the attribute key
217 * @return the attribute value or null if the attribute is undefined
218 */
219 public static String getAttribute( final Element node, final String key )
220 {
221 return getAttribute( node, key, null );
222 }
223
224 /**
225 * Return the value of an element attribute.
226 * @param node the DOM node
227 * @param key the attribute key
228 * @param def the default value if the attribute is undefined
229 * @return the attribute value or the default value if undefined
230 */
231 public static String getAttribute( final Element node, final String key, final String def )
232 {
233 if( null == node )
234 {
235 return def;
236 }
237 if( !node.hasAttribute( key ) )
238 {
239 return def;
240 }
241 //final String value = node.getAttribute( key );
242 //return normalize( value );
243 return node.getAttribute( key );
244 }
245
246 /**
247 * Return the value of an element attribute as a boolean
248 * @param node the DOM node
249 * @param key the attribute key
250 * @return the attribute value as a boolean or false if undefined
251 */
252 public static boolean getBooleanAttribute( final Element node, final String key )
253 {
254 return getBooleanAttribute( node, key, false );
255 }
256
257 /**
258 * Return the value of an element attribute as a boolean.
259 * @param node the DOM node
260 * @param key the attribute key
261 * @param def the default value if the attribute is undefined
262 * @return the attribute value or the default value if undefined
263 */
264 public static boolean getBooleanAttribute( final Element node, final String key, final boolean def )
265 {
266 if( null == node )
267 {
268 return def;
269 }
270
271 if( !node.hasAttribute( key ) )
272 {
273 return def;
274 }
275
276 String value = node.getAttribute( key );
277 value = normalize( value );
278 if( value.equals( "" ) )
279 {
280 return def;
281 }
282 if( value.equalsIgnoreCase( "true" ) )
283 {
284 return true;
285 }
286 if( value.equalsIgnoreCase( "false" ) )
287 {
288 return false;
289 }
290 final String error =
291 "Boolean argument [" + value + "] not recognized.";
292 throw new IllegalArgumentException( error );
293 }
294
295 /**
296 * Parse the value for any property tokens relative to system properties.
297 * @param value the value to parse
298 * @return the normalized string
299 */
300 static String normalize( String value )
301 {
302 return normalize( value, System.getProperties() );
303 }
304
305 /**
306 * Parse the value for any property tokens relative to the supplied properties.
307 * @param value the value to parse
308 * @param props the reference properties
309 * @return the normalized string
310 */
311 static String normalize( String value, Properties props )
312 {
313 return PropertyResolver.resolve( props, value );
314 }
315 }